<template>
  <div class="outer-container">
    <context-holder/>
    <Layout class="layout1">
      <!-- 侧边栏 -->
      <LayoutSider class="sider">
        <Flex gap="middle" vertical>
          <Button type="primary" size="large" style="width: 100%;">
            <template #icon>
              <PlusOutlined/>
            </template>
            新建对话
          </Button>
          <Button style="width: 100%;">当前对话</Button>
        </Flex>
      </LayoutSider>
      <Layout>
        <!-- 头部 -->
        <LayoutHeader class="header">金辉助手AI</LayoutHeader>
        <!-- 聊天内容区域 -->
        <LayoutContent class="content">
          <!-- 聊天列表 -->
          <ul class="chat-list" ref="messageListRef">
            <li class="chat-item" :class="`chat-item--${msg.role}`" v-for="msg in chatMessages">
              <MdPreview style="padding: 0; background-color: transparent;" type="String" :model-value="msg.content"/>
            </li>
            <li class="chat-item chat-item--system" :class="{ hidden: !isLoading }">
              <MdPreview :model-value="messagePlaceholder"/>
              <Spin/>
            </li>
          </ul>
        </LayoutContent>
        <!-- 底部 -->
        <LayoutFooter class="footer">
          <!-- 聊天输入框 -->
          <InputGroup>
            <Input v-model:value="userInputContent" @press-enter="sendChatMessage"/>
            <Button type="primary" @click="sendChatMessage">发送</Button>
          </InputGroup>
        </LayoutFooter>
      </Layout>
    </Layout>
  </div>
</template>

<script lang="ts" setup>
import {PlusOutlined} from '@ant-design/icons-vue';
import axios from 'axios';
import {
  Button,
  Flex,
  Input,
  InputGroup,
  Layout,
  LayoutContent,
  LayoutFooter,
  LayoutHeader,
  LayoutSider,
  message,
  Spin
} from 'ant-design-vue';
import {nextTick, ref} from 'vue';
import {fetchEventSource} from "@microsoft/fetch-event-source";
import {MdPreview} from 'md-editor-v3';
import 'md-editor-v3/lib/preview.css';
// import chatApi from './assets/api/chatApi';

type UserRole = 'system' | 'human';
const [messageApi, contextHolder] = message.useMessage();
const ctrl = new AbortController()
// 聊天信息列表
const chatMessages = ref([
  {
    role: 'system',
    content: "我是聊天机器人，有什么问题",
  },
]);

// 添加聊天信息
const addChatMessage = (role: UserRole, content: string) => {
  chatMessages.value.push({role, content});
  nextTick(() => {
    scrollToBottom()
  })
};

// 用户输入内容
const userInputContent = ref('');
// 加载状态
const isLoading = ref(false);
// 占位符
const messagePlaceholder = ref('')

// 发送信息
const sendChatMessage = () => {
  const inputContent = userInputContent.value.trim();
  if (!inputContent) return messageApi.error('请输入要发送的消息');
  // 加载状态
  isLoading.value = true;
  // 添加用户消息
  addChatMessage('human', inputContent.replace('<', '< '));
  userInputContent.value = '';
  setTimeout(() => {
    // 请求获取ai回复数据
    fetchChatAIData(inputContent)
    // chatApi.chat1({'msg': inputContent}).then((response) => {
    //   messagePlaceholder.value += response.data
    //   // 添加消息到消息列表上
    //   addChatMessage('system', messagePlaceholder.value)
    //   // 清空占位符
    //   messagePlaceholder.value = ''
    //   isLoading.value = false;
    // })
  }, 2000);
};

/**
 * 获取ai消息数据
 */
const fetchChatAIData = (question: string) => {
  isLoading.value = true
  fetchEventSource(axios.defaults.baseURL+'/chat/zp2', {
    method: 'post',
    headers: {
      "Accept": "text/event-stream",
      "Content-Type": "application/json; charset=UTF-8",
    },
    body: JSON.stringify({
      'msg': question
    }),
    onmessage(event) {
      let decodedString = base64DecodeUnicode(event.data);
      messagePlaceholder.value += decodedString;
      // 下滑
      nextTick(() => {
        scrollToBottom()
      })
    },
    onclose() {
      addChatMessage('system', messagePlaceholder.value); // 去除可能存在的尾部换行符
      messagePlaceholder.value = '';
      isLoading.value = false;
    },
    onerror(err) {
      ctrl.abort();
      isLoading.value = false;
    },
    signal: ctrl.signal
  });
}
// base64解码
const base64DecodeUnicode = (base64: string) => {
  // 将Base64字符串转换为二进制字符串（这里会包含一些不可见的字符）
  let binaryString = atob(base64);
  // 创建一个长度为二进制字符串长度的Uint8Array
  let len = binaryString.length;
  let bytes = new Uint8Array(len);
  for (let i = 0; i < len; i++) {
    bytes[i] = binaryString.charCodeAt(i);
  }
  // 使用TextDecoder将Uint8Array解码为字符串（支持Unicode）
  let decoder = new TextDecoder('utf-8');
  return decoder.decode(bytes);
}
// 引用消息列表的 DOM 元素
const messageListRef = ref<HTMLUListElement | null>(null);
// 滚动到底部的函数
const scrollToBottom = () => {
  if (messageListRef.value) {
    messageListRef.value.scrollTop = messageListRef.value.scrollHeight;
  }
};
</script>

<style lang="scss" scoped>
.outer-container {
  height: 95vh;
  width: 1272px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.layout1{
  min-width: 920px;
  height: 90%;
  border: #d6d6d6 solid 1px;
}

:deep(.md-editor-preview-wrapper) {
  padding: 0;
  background-color: transparent;
}

.header {
  background-color: #fff;
  border-bottom: 1px solid #f0f0f0;
}

.content {
  display: flex;
  background-color: #fff;
  overflow: hidden;
}

.footer {
  padding: 16px;
  background-color: #fff;
}

.sider {
  display: flex;
  justify-content: stretch;
  padding: 10px;
  border-right: 1px solid #f0f0f0;
  background-color: #fff;
}

.hidden {
  display: none;
}

:deep(.ant-layout-sider-children) {
  width: 100%;
}

:deep(.ant-input-group) {
  display: flex !important;
}

:deep(.ant-input) {
  height: 45px;
}

:deep(.ant-btn) {
  height: 45px;
}

.chat-list {
  display: flex;
  flex-direction: column;
  list-style-type: none;
  flex: 1;
  width: 100%;
  padding: 15px !important;
  gap: 30px;
  margin: 0;
  overflow-y: auto;

  .chat-item {
    line-height: 30px;
    padding: 3px 12px;
    border-radius: 10px;

    &--human {
      background-color: #42ceff;
      align-self: flex-end;

      :deep(p) {
        color: #fff;
      }
    }

    &--system {
      align-self: flex-start;
      border: 1px solid #f0f0f0;
    }
  }
}
</style>
